package com.example.gobang.controller;

import com.example.gobang.game.*;
import com.example.gobang.mapper.UserMapper;
import com.example.gobang.model.GameReadyResponse;
import com.example.gobang.model.GameResponse;
import com.example.gobang.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

@Component
@Slf4j
public class GameController extends TextWebSocketHandler {
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RoomManager roomManager;
    @Autowired
    private OnlineUserManager userManager;
    @Autowired
    private UserMapper userMapper;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        GameReadyResponse response = new GameReadyResponse();
        User user = (User) session.getAttributes().get("user");
        if(user == null){
            response.setOk(false);
            response.setReason("用户尚未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        // 判断用户是否在房间中 根据RoomManager
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if(room == null){
            response.setOk(false);
            response.setReason("尚未匹配到");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        // 判断用户是否多开 根据OnlineUserManager
        if(userManager.getOnline(user.getUserId()) != null ||
                userManager.getOnlineRoom(user.getUserId()) != null){
            response.setOk(true);
            response.setReason("账号在别处登录");
            response.setMessage("repeatCollection");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        userManager.enterGameRoom(user.getUserId(), session);
        synchronized (room) {
            if (room.getUser1() == null) {
                room.setUser1(user);
                room.setBlackUser(user.getUserId());
                log.info("玩家 " + user.getUsername() + " 进入游戏房间");
                return;
            }
            if (room.getUser2() == null) {
                room.setUser2(user);
                log.info("玩家 " + user.getUsername() + " 进入游戏房间");
                noticeGameReady(room, room.getUser1(), room.getUser2());
                noticeGameReady(room, room.getUser2(), room.getUser1());
                return;
            }
        }
    }

    private void noticeGameReady(Room room, User thisUser, User thatUser) throws IOException {
        GameReadyResponse response = new GameReadyResponse();
        response.setMessage("gameReady");
        response.setOk(true);
        response.setReason("");
        response.setRoomId(room.getRoomId());
        response.setThisUserId(thisUser.getUserId());
        response.setThatUserId(thatUser.getUserId());
        response.setBlackUser(room.getBlackUser());
        WebSocketSession session = userManager.getOnlineRoom(thisUser.getUserId());
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if(user == null){
            System.out.println("当前未登录");
            return;
        }
        Room room = roomManager.getRoomByUserId(user.getUserId());
        room.putChess(message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if(user == null){
            return;
        }
        WebSocketSession onlineRoom = userManager.getOnlineRoom(user.getUserId());
        if(onlineRoom == session){
            userManager.exitGameRoom(user.getUserId());
            log.info("当前玩家 " + user.getUsername() + " 游戏房间连接异常");
        }
        noticeUserWin(user);
    }

    private void noticeUserWin(User user) throws IOException {
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if(room == null){
            return;
        }
        User thatUser = (user == room.getUser1() ? room.getUser2() : room.getUser1());
        WebSocketSession session = userManager.getOnlineRoom(thatUser.getUserId());
        if(session == null){
            // 说明另一个玩家也掉线了
            log.info("两个玩家都掉线");
            return;
        }
        GameResponse response = new GameResponse();
        response.setUserId(thatUser.getUserId());
        response.setWinner(thatUser.getUserId());
        response.setMessage("putChess");
        response.isOut = -1;
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        log.info("玩家 " + user.getUsername() + " 掉线");
        userMapper.winUser(thatUser.getUserId());
        userMapper.loseUser(user.getUserId());
        roomManager.remove(room.getRoomId(), room.getUser1().getUserId(), room.getUser2().getUserId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if(user == null){
            return;
        }
        WebSocketSession onlineRoom = userManager.getOnlineRoom(user.getUserId());
        if(onlineRoom == session){
            userManager.exitGameRoom(user.getUserId());
        }
        log.info("当前玩家 " + user.getUsername() + " 退出游戏房间");
        noticeUserWin(user);
    }
}
